/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.coreGenerator.base.configGenerator;

import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.cef.entity.config.CefConfig;
import com.inspur.edp.cef.entity.config.MgrConfig;
import com.inspur.edp.cef.entity.config.RepositoryConfig;

import java.util.ArrayList;

import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;

public abstract class GetConfigsMethodGenerator extends ClassMethodGenerator {
    protected GetConfigsMethodGenerator() {
    }

    @Override
    protected Block buildMethodBody() {
        java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> statements =
                new java.util.ArrayList<Statement>();
        addNewListStatement(statements);
        addBuildListStatements(statements);
        addReturnStatements(ast, statements);
        Block block = ast.newBlock();
        block.statements().addAll(statements);
        return block;
    }

    private void addNewListStatement(java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list) {
        ClassInstanceCreation classInstanceCreation = ast.newClassInstanceCreation();
        ParameterizedType classInstanceCreationType =
                ast.newParameterizedType(ast.newSimpleType(ast.newName("java.util.ArrayList")));
        classInstanceCreationType
                .typeArguments()
                .add(new TypeInfo(CefConfig.class).getType(ast));
        classInstanceCreation.setType(classInstanceCreationType);
        VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment();
        variableDeclarationFragment.setName(ast.newSimpleName("list"));
        variableDeclarationFragment.setInitializer(classInstanceCreation);
        VariableDeclarationStatement variableDeclarationStatement = ast.newVariableDeclarationStatement(variableDeclarationFragment);
        ParameterizedType classInstanceCreationType1 =
                ast.newParameterizedType(ast.newSimpleType(ast.newName("java.util.ArrayList")));
        classInstanceCreationType1
                .typeArguments()
                .add(new TypeInfo(CefConfig.class).getType(ast));
        variableDeclarationStatement.setType(classInstanceCreationType1);
        list.add(variableDeclarationStatement);
    }

    private void addBuildListStatements(
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list) {
        if (getHasConfig() == false) {
            return;
        }
        CefConfig config = getConfig();
        // DataValidator.CheckForNullReference(config, "CefConfig");
        addBuildConfigStatements(list, config);
    }

    //
    //         CefConfig config =new CefConfig();
    //         config.getID()="ID";
    //         config.SourceID="SourceID";
    //         config.DefaultNamespace="DefaultNamespace";
    //         config.MgrConfig=new MgrConfig();
    //         config.MgrConfig.Assembly="Assembly";
    //         config.MgrConfig.Class="Class";
    //         config.MgrConfig.ImpAssembly="ImpAssembly";
    //         config.MgrConfig.ImpClass="ImpClass";
    //         config.MgrConfig.AllInterfaceAssembly="AllInterfaceAssembly";
    //         config.MgrConfig.AllInterfaceClassName="AllInterfaceClassName";
    //         config.RepositoryConfig=new RepositoryConfig();
    //         config.RepositoryConfig.Assembly="Assembly";
    //         config.RepositoryConfig.Class="Class";
    //
    private void addBuildConfigStatements(
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, CefConfig config) {
        addDeclareCefConfig(list, config);
        addSetIDAttribute(list, config);
        addSetBEIDAttribute(list, config);
        addSetDotnetIDAttribute(list,config);
        addSetSourceIDAttribute(list, config);
        addSetDefaultNamespaceAttribute(list, config);
        addSetMgrConfigAttributeStatement(ast, list, config.getMgrConfig());
        addSetRepositoryConfigAttributeStatement(ast, list, config.getRepositoryConfig());
        addConfigToList(list, config);
    }

    private void addConfigToList(
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, CefConfig config) {
        MethodInvocation addInvocation = ast.newMethodInvocation();
        addInvocation.setExpression(ast.newSimpleName("list"));
        addInvocation.setName(ast.newSimpleName("add"));
        addInvocation.arguments().add(ast.newSimpleName("config"));
        list.add(ast.newExpressionStatement(addInvocation));
    }

    private void addDeclareCefConfig(
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, CefConfig config) {
        ClassInstanceCreation classInstanceCreation = ast.newClassInstanceCreation();
        SimpleType classInstanceCreationType = ast.newSimpleType(ast.newName("com.inspur.edp.cef.entity.config.CefConfig"));
        classInstanceCreation.setType(classInstanceCreationType);
        VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment();
        variableDeclarationFragment.setName(ast.newSimpleName("config"));
        variableDeclarationFragment.setInitializer(classInstanceCreation);
        VariableDeclarationStatement variableDeclarationStatement = ast.newVariableDeclarationStatement(variableDeclarationFragment);
        variableDeclarationStatement.setType(ast.newSimpleType(ast.newName("com.inspur.edp.cef.entity.config.CefConfig")));
        list.add(variableDeclarationStatement);
    }

    // region 简单属性
    private void addSetIDAttribute(
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, CefConfig config) {
        MethodInvocation setIdInvocation = ast.newMethodInvocation();
        setIdInvocation.setExpression(ast.newSimpleName("config"));
        setIdInvocation.setName(ast.newSimpleName("setID"));
        StringLiteral idLiteral = ast.newStringLiteral();
        idLiteral.setLiteralValue(config.getID());
        setIdInvocation.arguments().add(idLiteral);
        list.add(ast.newExpressionStatement(setIdInvocation));
    }

    private void addSetBEIDAttribute(
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, CefConfig config) {
        MethodInvocation setIdInvocation = ast.newMethodInvocation();
        setIdInvocation.setExpression(ast.newSimpleName("config"));
        setIdInvocation.setName(ast.newSimpleName("setBEID"));
        StringLiteral idLiteral = ast.newStringLiteral();
        idLiteral.setLiteralValue(config.getBEID()==null?"":config.getBEID());
        setIdInvocation.arguments().add(idLiteral);
        list.add(ast.newExpressionStatement(setIdInvocation));
    }

    private void addSetDotnetIDAttribute(
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, CefConfig config) {
        MethodInvocation setIdInvocation = ast.newMethodInvocation();
        setIdInvocation.setExpression(ast.newSimpleName("config"));
        setIdInvocation.setName(ast.newSimpleName("setDotnetID"));
        StringLiteral idLiteral = ast.newStringLiteral();
        idLiteral.setLiteralValue(config.getDotnetID());
        setIdInvocation.arguments().add(idLiteral);
        list.add(ast.newExpressionStatement(setIdInvocation));
    }
    private void addSetSourceIDAttribute(
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, CefConfig config) {
        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(ast.newSimpleName("config"));
        setInvocation.setName(ast.newSimpleName("setSourceID"));
        StringLiteral valueLiteral = ast.newStringLiteral();
        valueLiteral.setLiteralValue(config.getSourceID());
        setInvocation.arguments().add(valueLiteral);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    private void addSetDefaultNamespaceAttribute(
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, CefConfig config) {
        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(ast.newSimpleName("config"));
        setInvocation.setName(ast.newSimpleName("setDefaultNamespace"));
        StringLiteral valueLiteral = ast.newStringLiteral();
        valueLiteral.setLiteralValue(config.getDefaultNamespace());
        setInvocation.arguments().add(valueLiteral);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    // endregion

    // region MgrConfig相关
    public static void addSetMgrConfigAttributeStatement(
            AST ast, java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, MgrConfig config) {
        addNewMgrConfigAttribute(ast, list);
        addSetMgrAssemblyStatement(ast, list, config);
        addSetMgrClassStatement(ast, list, config);
        addSetMgrImpAssemblyStatement(ast, list, config);
        addSetMgrImpClassStatement(ast, list, config);
        addSetMgrAllInterfaceAssemblyStatement(ast, list, config);
        addSetMgrAllInterfaceClassNameStatement(ast, list, config);
    }

    private static void addNewMgrConfigAttribute(
            AST ast, java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list) {
        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(ast.newSimpleName("config"));
        setInvocation.setName(ast.newSimpleName("setMgrConfig"));
        ClassInstanceCreation mgrConfigCreation = ast.newClassInstanceCreation();
        mgrConfigCreation.setType(ast.newSimpleType(ast.newName("com.inspur.edp.cef.entity.config.MgrConfig")));
        setInvocation.arguments().add(mgrConfigCreation);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    private static void addSetMgrAssemblyStatement(
            AST ast, java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, MgrConfig config) {
        MethodInvocation getMgrConfigInvocation = ast.newMethodInvocation();
        getMgrConfigInvocation.setExpression(ast.newSimpleName("config"));
        getMgrConfigInvocation.setName(ast.newSimpleName("getMgrConfig"));

        MethodInvocation setAssemblyInvocation = ast.newMethodInvocation();
        setAssemblyInvocation.setExpression(getMgrConfigInvocation);
        setAssemblyInvocation.setName(ast.newSimpleName("setAssembly"));
        StringLiteral assemblyLiteral = ast.newStringLiteral();
        assemblyLiteral.setLiteralValue(config.getAssembly());
        setAssemblyInvocation.arguments().add(assemblyLiteral);
        list.add(ast.newExpressionStatement(setAssemblyInvocation));
    }

    private static void addSetMgrClassStatement(
            AST ast, java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, MgrConfig config) {
        MethodInvocation getMgrConfigInvocation = ast.newMethodInvocation();
        getMgrConfigInvocation.setExpression(ast.newSimpleName("config"));
        getMgrConfigInvocation.setName(ast.newSimpleName("getMgrConfig"));

        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(getMgrConfigInvocation);
        setInvocation.setName(ast.newSimpleName("setClass"));
        StringLiteral valueLiteral = ast.newStringLiteral();
        valueLiteral.setLiteralValue(config.getClassName());
        setInvocation.arguments().add(valueLiteral);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    private static void addSetMgrImpAssemblyStatement(
            AST ast, java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, MgrConfig config) {
//    MethodInvocation getMgrConfigInvocation = ast.newMethodInvocation();
//    getMgrConfigInvocation.setExpression(ast.newSimpleName("config"));
//    getMgrConfigInvocation.setName(ast.newSimpleName("getMgrConfig"));

//    MethodInvocation setInvocation = ast.newMethodInvocation();
//    setInvocation.setExpression(getMgrConfigInvocation);
//    setInvocation.setName(ast.newSimpleName("setImpAssembly"));
//    StringLiteral valueLiteral = ast.newStringLiteral();
//    valueLiteral.setLiteralValue(config.getImpAssembly());
//    setInvocation.arguments().add(valueLiteral);
//    list.add(ast.newExpressionStatement(setInvocation));
    }

    private static void addSetMgrImpClassStatement(
            AST ast, java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, MgrConfig config) {
        MethodInvocation getMgrConfigInvocation = ast.newMethodInvocation();
        getMgrConfigInvocation.setExpression(ast.newSimpleName("config"));
        getMgrConfigInvocation.setName(ast.newSimpleName("getMgrConfig"));

        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(getMgrConfigInvocation);
        setInvocation.setName(ast.newSimpleName("setImpClass"));
        StringLiteral valueLiteral = ast.newStringLiteral();
        valueLiteral.setLiteralValue(config.getImpClass());
        setInvocation.arguments().add(valueLiteral);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    private static void addSetMgrAllInterfaceAssemblyStatement(
            AST ast, java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, MgrConfig config) {
        MethodInvocation getMgrConfigInvocation = ast.newMethodInvocation();
        getMgrConfigInvocation.setExpression(ast.newSimpleName("config"));
        getMgrConfigInvocation.setName(ast.newSimpleName("getMgrConfig"));

        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(getMgrConfigInvocation);
        setInvocation.setName(ast.newSimpleName("setAllInterfaceAssembly"));
        StringLiteral valueLiteral = ast.newStringLiteral();
        valueLiteral.setLiteralValue(config.getAllInterfaceAssembly());
        setInvocation.arguments().add(valueLiteral);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    private static void addSetMgrAllInterfaceClassNameStatement(
            AST ast, java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list, MgrConfig config) {
        MethodInvocation getMgrConfigInvocation = ast.newMethodInvocation();
        getMgrConfigInvocation.setExpression(ast.newSimpleName("config"));
        getMgrConfigInvocation.setName(ast.newSimpleName("getMgrConfig"));

        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(getMgrConfigInvocation);
        setInvocation.setName(ast.newSimpleName("setAllInterfaceClassName"));
        StringLiteral valueLiteral = ast.newStringLiteral();
        valueLiteral.setLiteralValue(config.getAllInterfaceClassName());
        setInvocation.arguments().add(valueLiteral);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    // endregion

    public static void addSetRepositoryConfigAttributeStatement(
            AST ast,
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list,
            RepositoryConfig config) {
        if (config == null) {
            return;
        }
        addNewRepositoryConfigStatement(ast, list, config);
        addSetRepoAssemblyStatement(ast, list, config);
        addSetRepoClassStatement(ast, list, config);
    }

    private static void addNewRepositoryConfigStatement(
            AST ast,
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list,
            RepositoryConfig config) {
        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(ast.newSimpleName("config"));
        setInvocation.setName(ast.newSimpleName("setRepositoryConfig"));
        ClassInstanceCreation configCreation = ast.newClassInstanceCreation();
        configCreation.setType(ast.newSimpleType(ast.newName("com.inspur.edp.cef.entity.config.RepositoryConfig")));
        setInvocation.arguments().add(configCreation);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    private static void addSetRepoAssemblyStatement(
            AST ast,
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list,
            RepositoryConfig config) {
        MethodInvocation getMgrConfigInvocation = ast.newMethodInvocation();
        getMgrConfigInvocation.setExpression(ast.newSimpleName("config"));
        getMgrConfigInvocation.setName(ast.newSimpleName("getRepositoryConfig"));

        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(getMgrConfigInvocation);
        setInvocation.setName(ast.newSimpleName("setAssembly"));
        StringLiteral valueLiteral = ast.newStringLiteral();
        valueLiteral.setLiteralValue(config.getAssembly());
        setInvocation.arguments().add(valueLiteral);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    private static void addSetRepoClassStatement(
            AST ast,
            java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list,
            RepositoryConfig config) {
        MethodInvocation getMgrConfigInvocation = ast.newMethodInvocation();
        getMgrConfigInvocation.setExpression(ast.newSimpleName("config"));
        getMgrConfigInvocation.setName(ast.newSimpleName("getRepositoryConfig"));

        MethodInvocation setInvocation = ast.newMethodInvocation();
        setInvocation.setExpression(getMgrConfigInvocation);
        setInvocation.setName(ast.newSimpleName("setClass"));
        StringLiteral valueLiteral = ast.newStringLiteral();
        valueLiteral.setLiteralValue(config.getClassName());
        setInvocation.arguments().add(valueLiteral);
        list.add(ast.newExpressionStatement(setInvocation));
    }

    private void addReturnStatements(
            AST ast, java.util.ArrayList<org.eclipse.jdt.core.dom.Statement> list) {
        ReturnStatement returnStatement = ast.newReturnStatement();
        returnStatement.setExpression(ast.newSimpleName("list"));
        list.add(returnStatement);
    }

    @Override
    protected java.util.ArrayList<ModifierKeyword> getAccessModifiers() {
        return new java.util.ArrayList<ModifierKeyword>(
                java.util.Arrays.asList(new ModifierKeyword[]{ModifierKeyword.PUBLIC_KEYWORD}));
    }

    @Override
    protected String getMethodName() {
        return "getConfigs";
    }

    @Override
    protected java.util.ArrayList<ParameterInfo> getParameterCollection() {
        return new java.util.ArrayList<ParameterInfo>();
    }

    @Override
    protected TypeInfo getReturnType() {
        TypeInfo info = new TypeInfo(java.util.ArrayList.class);
        info.setIsParameterizedType(true);
        ArrayList<TypeInfo> genericTyeps = new ArrayList<>(1);
        genericTyeps.add(new TypeInfo(CefConfig.class));
        info.setArguments(genericTyeps);
        return info;
    }

    protected abstract boolean getHasConfig();

    protected abstract CefConfig getConfig();

    CefConfig getCefConfig() {
        return getConfig();
    }
//
//    @Override
//    protected final boolean getIsOverride() {
//        return true;
//    }
}
